package com.threeti.mecool.mobile.controller.demo;

import com.threeti.mecool.core.application.init.Initializer;
import com.threeti.mecool.core.domain.model.acl.PermissionRoleAchievement;
import com.threeti.mecool.core.domain.model.acl.User;
import com.threeti.mecool.core.domain.model.plan.PlanJobResult;
import com.threeti.mecool.core.domain.model.plan.PlanResult;
import com.threeti.mecool.core.domain.model.plan.ProjectCriticalJob;
import com.threeti.mecool.core.domain.model.plan.UserStepResult;
import com.threeti.mecool.core.domain.model.plan.pojo.*;
import com.threeti.mecool.core.domain.model.project.Project;
import com.threeti.mecool.core.infrastructure.persistence.acl.PermissionRoleAchievementRepository;
import com.threeti.mecool.core.infrastructure.persistence.acl.UserRepository;
import com.threeti.mecool.core.infrastructure.persistence.plan.ProjectCriticalJobRepository;
import com.threeti.mecool.core.infrastructure.persistence.project.ProjectRepository;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import java.util.*;

@Controller
@RequestMapping("/demo/plan")
public class PlanController {
    private Logger logger = LoggerFactory.getLogger(PlanController.class);
    private ProjectRepository projectRepository;
    private UserRepository userRepository;
    private PermissionRoleAchievementRepository achievementRepository;
    private ProjectCriticalJobRepository criticalJobRepository;

    @RequestMapping("/add_plan/{userLoginName}/{planDate}")
    @ResponseBody
    public Map<String, Object> addPlan(@PathVariable String userLoginName, @PathVariable @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date planDate) {
        Map<String, Object> ret = new HashMap<String, Object>();
        try {
            Plan plan = createSamplePlan(planDate, userLoginName);
            ret.put("plan", plan);
        } catch (Exception e) {
            logger.error("error create demo plan", e);
            ret.put("err", e);
        }
        return ret;
    }

    @RequestMapping("/confirm/{plan_id}")
    @ResponseBody
    public Map<String, Object> confirmPlan(@PathVariable("plan_id") Long planId) {
        Plan plan = Plan.findById(planId);
        plan.setStatus(Plan.STATUS_CONFIRM);
        plan.save();
        return new HashMap<String, Object>();
    }

    @RequestMapping("/rm_plan/{planId}")
    @ResponseBody
    public Map<String, Object> removePlan(@PathVariable Long planId) {
        Plan plan = Plan.findById(planId);
        if (plan != null) {
            plan.delete();
        }
        return new HashMap<String, Object>();
    }

    @RequestMapping("/mock_plan_result")
    @ResponseBody
    public String mockPlanResult(@RequestParam("planId") Long planId) {
        try {
            final Random random = new Random(System.currentTimeMillis());
            PlanResult planResult = PlanResult.optByPlanId(planId);
            for (PlanJobResult planJobResult : planResult.getPlanJobResults()) {
                if (planJobResult.getFinishedAt() == null) {
                    String jobName = planJobResult.getPlanJob().getJob().getName();
//                    if ("开店".equals(jobName) || "巡店".equals(jobName) || "踩点办证".equals(jobName)) {
                        for (Step step : planJobResult.getPlanJob().getJob().getSteps()) {
                            UserStepResult userStepResult = planJobResult.optUserStepResult(step.getId());
                            setupUserStepResult(userStepResult);
                            for (StepItem stepItem : step.getStepItems()) {
                                for (Step stepItemStep : stepItem.getSteps()) {
                                    UserStepResult stepResult = planJobResult.optUserStepResult(stepItemStep.getId());
                                    setupUserStepResult(stepResult);
                                }
                            }
                        }
                        planJobResult.setFinishedAt(new Date());
                        planJobResult.setJobStatus(PlanJobResult.JOB_STATUS_FINISHED);
//                    } else {
//                        planJobResult.setFinishedAt(new Date());
//                        planJobResult.setJobStatus(PlanJobResult.JOB_STATUS_NOT_FINISHED);
//                        planJobResult.setNotes("无法mock数据");
//                    }
                }
            }
            planResult.save();
            return "ok";
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping("/find")
    @ResponseBody
    public Page<Plan> findPagedPlan(@RequestParam("user") String userLoginName, Pageable pageable) {
        return Plan.findByUserLoginName(userLoginName, pageable);
    }

    private void setupUserStepResult(UserStepResult userStepResult) {
        System.out.println("userStepResult.getStep().getId() = " + userStepResult.getStep().getId());
        switch (userStepResult.getActionId()) {
            case TaskAction.ID_INPUT_TEXT:
                userStepResult.setData(RandomStringUtils.random(6, "应用程序位置系统拼音"));
                break;
            case TaskAction.ID_INPUT_NUMBER:
                userStepResult.setData(String.valueOf(RandomUtils.nextInt(200)));
                break;
            case TaskAction.ID_TAKE_PHOTO:
                userStepResult.setData("/" + RandomUtils.nextInt(3) + ".jpg");
                break;
            case TaskAction.ID_SELECT_SINGLE:
                userStepResult.setData(String.valueOf(RandomUtils.nextInt(userStepResult.getStep().getStepItems().size())));
                break;
            default:
                userStepResult.setData("");
        }
        userStepResult.setLatitude(31d);
        userStepResult.setLongitude(121d);
        userStepResult.setFinishedAt(new Date());
    }

    @RequestMapping("/auto_plan")
    @ResponseBody
    public Plan autoPlan(@RequestParam("userLoginName") String userLoginName,
                         @RequestParam("projectCode") String projectCode,
                         @RequestParam("storeCode") String storeCode,
                         @RequestParam("jobId") Long jobId,
                         @RequestParam("planDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date planDate,
                         @RequestParam("startTime") @DateTimeFormat(pattern = "HH:mm") Date startTime,
                         @RequestParam("endTime") @DateTimeFormat(pattern = "HH:mm") Date endTime) {
        Plan plan = Plan.optAssignedPlanBy(userLoginName, projectCode, storeCode, jobId, planDate, startTime, endTime);
        return plan;
    }

    private Job createFootPrintAndCertJob() {
      return Initializer.createFootPrintAndCertJob();
    }

    private Job createOpenStoreJob() {
      return Initializer.createOpenStoreJob();
    }

    private Job createPatrolJob() {
      return Initializer.createPatrolJob();
    }

    private Job createScoreJob() {
        return Initializer.createScoreJob();
    }

    private Job createAttachmentJob() {
        return Initializer.createAttachmentJob();
    }

    @Resource
    public void setProjectRepository(ProjectRepository projectRepository) {
        this.projectRepository = projectRepository;
    }

    @Resource
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Resource
    public void setAchievementRepository(PermissionRoleAchievementRepository achievementRepository) {
        this.achievementRepository = achievementRepository;
    }

    @Resource
    public void setCriticalJobRepository(ProjectCriticalJobRepository criticalJobRepository) {
        this.criticalJobRepository = criticalJobRepository;
    }

    private Plan createSamplePlan(Date date, String userLoginName) {
        Plan plan = new Plan();
        plan.setUserLoginName(userLoginName);
        DateTime planDate = new DateTime(date).withTime(0, 0, 0, 0);
        plan.setPlanDate(planDate.toDate());
        plan.setName("工作计划 - " + planDate.toString("yyyy-MM-dd"));

        DateTime jobBaseTime = new DateTime(0);
        Job job = createFootPrintAndCertJob();
        Job openStoreJob = createOpenStoreJob();
        Job patrolJob = createPatrolJob();
        Job scoreJob = createScoreJob();
        Job attachmentJob = createAttachmentJob();

        //<editor-fold desc="confirm PermissionRoleAchievement">
        User user = userRepository.findByloginName(userLoginName);
        List<PermissionRoleAchievement> achievementList = achievementRepository.findByPermissionRole(user.getPermissionRole());
        boolean hasPatrolAchievement = false;
        for (PermissionRoleAchievement achievement : achievementList) {
            if (patrolJob.getId().equals(achievement.getJob().getId())) {
                hasPatrolAchievement = true;
                break;
            }
        }
        if (!hasPatrolAchievement) {
            PermissionRoleAchievement achievement = new PermissionRoleAchievement();
            achievement.setJob(patrolJob);
            achievement.setPermissionRole(user.getPermissionRole());
            achievement.setTargetCount(20);
            achievementRepository.save(achievement);
        }
        //</editor-fold>
        //<editor-fold desc="critical job">
        List<ProjectCriticalJob> criticalJobList = criticalJobRepository.findByProject_CodeAndJob_Id("1001", openStoreJob.getId());
        boolean hasCriticalJob = false;
        for (ProjectCriticalJob criticalJob : criticalJobList) {
            if (openStoreJob.getId().equals(criticalJob.getJob().getId())) {
                hasCriticalJob = true;
                break;
            }
        }
        if (!hasCriticalJob) {
            ProjectCriticalJob criticalJob = new ProjectCriticalJob();
            Project project = projectRepository.findByCode("1001");
            criticalJob.setProject(project);
            criticalJob.setJob(openStoreJob);
            criticalJob.setStartTime(new DateTime(2012, 7, 10, 0, 0).toDate());
            criticalJob.setEndTime(new DateTime(2012, 7, 15, 0, 0).toDate());
            criticalJobRepository.save(criticalJob);
        }
        //</editor-fold>

        PlanProject planProject = new PlanProject();
        planProject.setProjectCode("1001");
        PlanJob planJob = new PlanJob();
        planJob.setJob(openStoreJob);
        planJob.setStoreCode("31010610001018000641");
        planJob.setStartTime(jobBaseTime.withTime(7, 0, 0, 0).toDate());
        planJob.setEndTime(jobBaseTime.withTime(11, 0, 0, 0).toDate());
        planProject.addPlanJob(planJob);

        PlanJob attachmentPlanJob = new PlanJob();
        attachmentPlanJob.setJob(attachmentJob);
        attachmentPlanJob.setStoreCode("31010610001018000641");
        attachmentPlanJob.setStartTime(jobBaseTime.withTime(11, 0, 0, 0).toDate());
        attachmentPlanJob.setEndTime(jobBaseTime.withTime(11, 30, 0, 0).toDate());
        planProject.addPlanJob(attachmentPlanJob);

        PlanJob patrolPlanJob = new PlanJob();
        patrolPlanJob.setJob(patrolJob);
        patrolPlanJob.setStoreCode("31010610001008000642");
        patrolPlanJob.setStartTime(jobBaseTime.withTime(13, 0, 0, 0).toDate());
        patrolPlanJob.setEndTime(jobBaseTime.withTime(13, 30, 0, 0).toDate());
        planProject.addPlanJob(patrolPlanJob);

        PlanProject planProject_1 = new PlanProject();
        planProject_1.setProjectCode("1002");
        PlanJob testPlanJob = new PlanJob();
        testPlanJob.setJob(job);
        testPlanJob.setStoreCode("61010120001023000001");
        testPlanJob.setStartTime(jobBaseTime.withTime(14, 0, 0, 0).toDate());
        testPlanJob.setEndTime(jobBaseTime.withTime(18, 0, 0, 0).toDate());
        planProject_1.addPlanJob(testPlanJob);

        PlanJob scorePlanJob = new PlanJob();
        scorePlanJob.setJob(scoreJob);
        scorePlanJob.setStoreCode("61010120001023000001");
        scorePlanJob.setStartTime(jobBaseTime.withTime(18, 0, 0, 0).toDate());
        scorePlanJob.setEndTime(jobBaseTime.withTime(18, 30, 0, 0).toDate());
        planProject_1.addPlanJob(scorePlanJob);

        plan.addPlanProject(planProject);
        plan.addPlanProject(planProject_1);
//        plan.setStatus(Plan.STATUS_CONFIRM);
        plan.save();
        return plan;
    }

}
